package com.itlong.cloud.controller.finance;

import com.itlong.cloud.POJO.DTO.operate.OperateCheckAccountByPageDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateUpdateOrderStatusDTO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.operate.OperateCheckAccountGetPageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.enumerate.FileCatalogEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.OperateErrorCodeEnum;
import com.itlong.cloud.paymenthub.ICheckAccountServiceClient;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 * 运营-财务管理模块-自动对账出主控制器.
 * </desc>
 *
 * @createDate 2018/9/19
 */
@RestController
@RequestMapping("/finance")
@RefreshScope
public class OperateCheckAccountController {

    private static final Logger LOG = LoggerFactory.getLogger(OperateCheckAccountController.class);

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;
    @Autowired
    ICheckAccountServiceClient iCheckAccountServiceClient;

    /**
     * <desc>
     *      自动对账出入列表展示
     * <desc/>
     *
     * @param checkAccountByPageDTO 查询条件
     * @return
     * @author Juguang.S
     * @createDate 2018-09-19
     */
    @ResponseBody
    @AuthAccessRequired
    @RequestMapping(path = "/checkAccount/autoCheckDiffInfo", method = RequestMethod.POST)
    public Object autoCheckDiffInfo(OperateCheckAccountByPageDTO checkAccountByPageDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            checkAccountByPageDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateCheckAccountByPageDTO.class,request);
            // 判断时间区间的合法性
            if (StringUtils.isNotBlank(checkAccountByPageDTO.getStartTime()) && StringUtils.isNotBlank(checkAccountByPageDTO.getEndTime())) {
                Date startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(checkAccountByPageDTO.getStartTime());
                Date endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(checkAccountByPageDTO.getEndTime());
                // 开始时间必须小于结束时间
                if (startTime.after(endTime)) {
                    return new MessageVO(OperateErrorCodeEnum.TIME_AVAILABLE_ERR.getErrorCode());
                }
            }
            Page<OperateCheckAccountGetPageVO> page = iCheckAccountServiceClient.getCheckDiffInfoByPage(checkAccountByPageDTO);

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),page);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务管理】自动对账出入表获取分页列表失败",e);
        }
    }

    /**
     * <desc>
     *      根据ID查询其备注和订单状态
     * <desc/>
     *
     * @param orderDiffId id
     * @return
     * @author Juguang.S
     * @createDate 2018-09-19
     */
    @ResponseBody
    @RequestMapping(path = "/checkAccount/getCheckInfo", method = RequestMethod.POST)
    public Object getCheckInfo(String orderDiffId){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            orderDiffId=request.getAttribute("orderDiffId")==null?null:request.getAttribute("orderDiffId").toString();
            if(StringUtils.isEmpty(orderDiffId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            Map<String,Object> map = iCheckAccountServiceClient.getCheckInfo(orderDiffId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务管理】根据ID查询其备注和订单状态失败",e);
        }
    }

    /**
     * <desc>
     *      根据ID修改其备注和订单状态
     * <desc/>
     *

     * @return
     * @author Juguang.S
     * @createDate 2018-09-19
     */
    @ResponseBody
    @AuthAccessRequired
    @RequestMapping(path = "/checkAccount/updateStatus", method = RequestMethod.POST)
    @LoggerInfo(operateDesc = LogDescConstant.CHECK_ACCOUNT_UPDATE_REMARK_STATUS_DESC)
    public Object updateStatus(OperateUpdateOrderStatusDTO orderStatusDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            orderStatusDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateUpdateOrderStatusDTO.class,request);
            String remark = orderStatusDTO.getRemark();
            if(StringUtils.isEmpty(orderStatusDTO.getOrderDiffId()) || StringUtils.isEmpty(orderStatusDTO.getDiffOrderStatus()) || StringUtils.isEmpty(orderStatusDTO.getMyUserName())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if(StringUtils.isEmpty(remark)){
                remark = "";
                orderStatusDTO.setRemark(remark);
            }
            iCheckAccountServiceClient.updateStatus(orderStatusDTO.getOrderDiffId(),orderStatusDTO.getDiffOrderStatus(),remark,orderStatusDTO.getMyUserName());
            return new MessageVO(orderStatusDTO.getOrderDiffId(),BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【运营-财务管理】根据ID查询其备注和订单状态失败",e);
        }
    }

    /**
     * <desc>
     *      将自动对账出入表中的数据导出
     * <desc/>
     *
     * @param checkAccountByPageDTO 条件
     * @return
     * @author Juguang.S
     * @createDate 2018-09-19
     */
    @ResponseBody
    @AuthAccessRequired
    @RequestMapping(path = "/checkAccount/exportDiffInfo", method = RequestMethod.POST)
    public Object exportDiffInfo(OperateCheckAccountByPageDTO checkAccountByPageDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            checkAccountByPageDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateCheckAccountByPageDTO.class,request);
            List<OperateCheckAccountGetPageVO> diffPOS = iCheckAccountServiceClient.getDiffInfo(checkAccountByPageDTO);
            if (diffPOS == null || diffPOS.isEmpty()) {
                return new MessageVO(OperateErrorCodeEnum.EXPORT_DATA_EMPTY_ERR.getErrorCode());
            }
            String[] title = {"序号","应用appid","商户号","商户订单号","微信订单号","微信交易金额","商户交易金额","出入类型","下单时间","交易成功时间","创建时间","订单状态","审批人","备注"};
            short rowHeight= 420;
            //创建excel工作簿
            HSSFWorkbook workbook=new HSSFWorkbook();
            //创建工作表sheet并设置简单格式
            HSSFSheet sheet=workbook.createSheet();
            sheet.setDefaultColumnWidth(16);
            //创建第一行
            HSSFRow row=sheet.createRow(0);
            row.setHeight(rowHeight);
            HSSFCell cell=null;
            //插入第一行数据的表头
            for (int i = 0; i < title.length; i++) {
                cell = row.createCell(i);
                cell.setCellValue(title[i]);
            }
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //写入数据
            for (int carIndex = 0; carIndex < diffPOS.size(); carIndex++) {
                OperateCheckAccountGetPageVO accountGetPageVO = diffPOS.get(carIndex);
                int rowIndex = carIndex + 1; // 第一行已为标题行
                HSSFRow dataRow = sheet.createRow(rowIndex);
                dataRow.setHeight(rowHeight);
                HSSFCell noteCell = dataRow.createCell(0);
                noteCell.setCellValue(rowIndex);
                noteCell = dataRow.createCell(1);
                noteCell.setCellValue(accountGetPageVO.getAppid());
                noteCell = dataRow.createCell(2);
                noteCell.setCellValue(accountGetPageVO.getMchid());
                noteCell = dataRow.createCell(3);
                noteCell.setCellValue(accountGetPageVO.getBussinessOrderNum());
                noteCell = dataRow.createCell(4);
                noteCell.setCellValue(accountGetPageVO.getWechatOrderNum());
                noteCell = dataRow.createCell(5);
                if(StringUtils.isEmpty(accountGetPageVO.getWechatTradeAmount())){
                    noteCell.setCellValue("");
                }else{
                    noteCell.setCellValue(accountGetPageVO.getWechatTradeAmount());
                }
                noteCell = dataRow.createCell(6);
                if(StringUtils.isEmpty(accountGetPageVO.getBussinessTradeAmount())){
                    noteCell.setCellValue("");
                }else{
                    noteCell.setCellValue(accountGetPageVO.getBussinessTradeAmount());
                }
                noteCell = dataRow.createCell(7);
                if (accountGetPageVO.getDiffType() != null) {
                    switch (accountGetPageVO.getDiffType()){
                        case 1:
                            noteCell.setCellValue("短款");
                            break;
                        case 2:
                            noteCell.setCellValue("长款");
                            break;
                        case 3:
                            noteCell.setCellValue("金额不一致");
                            break;
                        default:
                            break;
                    }
                } else {
                    noteCell.setCellValue("");
                }
                noteCell = dataRow.createCell(8);
                noteCell.setCellValue(accountGetPageVO.getOrderTime());
                noteCell = dataRow.createCell(9);
                noteCell.setCellValue(accountGetPageVO.getTradeSuccessTime());
                noteCell = dataRow.createCell(10);
                noteCell.setCellValue(accountGetPageVO.getCreateTime());
                noteCell = dataRow.createCell(11);
                if (accountGetPageVO.getDiffOrderStatus() != null) {
                    switch (accountGetPageVO.getDiffOrderStatus()){
                        case 1:
                            noteCell.setCellValue("已平账");
                            break;
                        case 2:
                            noteCell.setCellValue("未平账");
                            break;
                        default:
                            break;
                    }
                } else {
                    noteCell.setCellValue("");
                }
                noteCell = dataRow.createCell(12);
                noteCell.setCellValue(accountGetPageVO.getOperator());
                noteCell = dataRow.createCell(13);
                noteCell.setCellValue(accountGetPageVO.getRemark());
            }
            String fileName = String.format("CheckAccountInfo_%s.xls",
                    DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));

            fileName = URLEncoder.encode(fileName, "UTF-8");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);
            byte[] content = os.toByteArray();
            InputStream exportFileStream = new ByteArrayInputStream(content);
            String exportFileUrl = this.uploadFile(exportFileStream,fileName);
            if (StringUtils.isBlank(exportFileUrl)){
                return new MessageVO(OperateErrorCodeEnum.EXPORT_FILE_SAVE_ERR.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), (Object) exportFileUrl);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务管理】导出自动对账出入表信息失败",e);
        }
    }

    /**
     * <desc>
     *      Ftp上传文件，返回Url.
     * </desc>
     *
     * @param inputStream 文件流
     * @param fileName 文件名称
     * @return 文件上传成功后会返回Url,否则返回空
     * @author wangzhi
     * @createDate 2018/08/22
     */
    private String uploadFile(InputStream inputStream, String fileName) throws IOException {
        String fileUrl = "";
        String fileType = StringHandlerUtil.copySubStr(fileName, fileName.lastIndexOf('.') + 1, fileName.length());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                inputStream,
                fileType,
                FILE_ACCESS_URL,
                FileCatalogEnum.EXPORT_EXCEL_ZHANG_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == false){
            return fileUrl;
        }
        fileUrl = resultMap.get("accessPath").toString();
        return fileUrl;
    }
}